﻿#region Copyright Notice
// 
// 
//  
//  Copyright (c) 2009-2011 Anindya Chatterjee
//  
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//  
//      http://www.apache.org/licenses/LICENSE-2.0
//  
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// 
// 
#endregion
using System;

namespace AbstractClass.NPerf.Framework
{
    /// <summary>
    /// Represents a type which verifies the data generated by a test against the specified data.
    /// </summary>
    public class Constraint
    {
        internal ConstraintType ConstraintType { get; set; }

        internal object ObjA { get; set; }
        internal object ObjB { get; set; }

        internal void Evaluate(object value)
        {
            if (ObjA != null && value != null)
            {
                try
                {
                    double tempValue = Convert.ToDouble(value);
                    var decValue = (decimal) Math.Round(tempValue, 2);

                    double tempObjA = Convert.ToDouble(ObjA);
                    var decObjA = (decimal) Math.Round(tempObjA, 2);

                    switch (ConstraintType)
                    {
                        case ConstraintType.EqualTo:
                            if (decValue != decObjA)
                                throw new AssertionException(string.Format(LanguageResource.EqualToFailed, ObjA, value));
                            return;
                        case ConstraintType.GreaterThan:
                            if (decValue <= decObjA)
                                throw new AssertionException(string.Format(LanguageResource.GreaterThanFailed, value,
                                                                           ObjA));
                            return;
                        case ConstraintType.LesserThan:
                            if (decValue >= decObjA)
                                throw new AssertionException(string.Format(LanguageResource.LesserThanFailed, value,
                                                                           ObjA));
                            return;
                        case ConstraintType.GreaterOrEqualTo:
                            if (decValue < decObjA)
                                throw new AssertionException(string.Format(LanguageResource.GreaterOrEqualFailed, value,
                                                                           ObjA));
                            return;
                        case ConstraintType.LesserOrEqualTo:
                            if (decValue > decObjA)
                                throw new AssertionException(string.Format(LanguageResource.LesserOrEqualFailed, value,
                                                                           ObjA));
                            return;
                        case ConstraintType.InBetween:
                            if (ObjB == null)
                                throw new AssertionException(LanguageResource.UnspecifiedRange);

                            double tempObjB = Convert.ToDouble(ObjB);
                            var decObjB = (decimal) Math.Round(tempObjB, 2);

                            if (decObjA <= decValue && decValue <= decObjB)
                                return;
                            throw new AssertionException(string.Format(LanguageResource.InBetweenFailed, value, ObjA,
                                                                       ObjB));
                        case ConstraintType.NotEqualTo:
                            if (decValue == decObjA)
                                throw new AssertionException(string.Format(LanguageResource.NotEqualToFailed, value,
                                                                           ObjA));
                            return;
                    }
                }
                catch (AssertionException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new AssertionException(LanguageResource.UnhandledException, e);
                }

                throw new AssertionException(LanguageResource.ExpectedValueCantBeNull);
            }
        }
    }
}